//! @Author: DengLibin
//! @Date: Create in 2024-07-17 13:41:12
//! @Description:

use std::sync::{
    atomic::{AtomicUsize, Ordering},
    Arc,
};

use log::info;
use my_util_lib::log_util;
use snowflaker::generator::SnowflakeGenerator;
use sqlx::{MySql, Pool};
use tokio::task;

use crate::{
    dao,
    sys::{
        config::{self, AppConfig},
        global::{to_global_result, GlobalResult},
    },
};

///全局状态
pub struct AppState {
    //配置信息
    pub app_config: AppConfig,
    //数据库连接池
    pub pool: Pool<MySql>,
    //异步阻塞任务数量
    pub async_task_num: AtomicUsize,
    //雪花算法
    pub snowflaker: SnowflakeGenerator,
}

/// @Author: DengLibin
/// @Date: Create in 2023-11-06 15:10:01
/// @Description: 日志初始化
pub async fn init_log() -> GlobalResult<()> {
    let r = log_util::init_log(r"log4rs.yaml");
    to_global_result(r)
}

pub async fn init_mysql_db(config: &AppConfig) -> GlobalResult<Pool<MySql>> {
    let pool = dao::mysql::mysql_dao::get_conn_pool(&config.mysql_url, config.max_conn).await;
    to_global_result(pool)
}

/// @Author: DengLibin
/// @Date: Create in 2023-11-06 15:10:09
/// @Description: 初始化
pub async fn init() -> GlobalResult<AppState> {
    init_log().await?;
    info!("日志初始化完成");

    // 阻塞任务
    let app_config_handle =
        tokio::task::spawn_blocking(|| config::read_yaml_config("application.yml"));
    let app_config = to_global_result(to_global_result(app_config_handle.await)?)?;
    info!("配置文件读取成功：{:?}", app_config);
    let pool = init_mysql_db(&app_config).await?;
    info!("连接数据库连池创建成功:{}", app_config.mysql_url);
    //雪花算法
    let snowflaker = to_global_result(SnowflakeGenerator::builtin())?;
    Ok(AppState {
        app_config: app_config,
        pool: pool,
        async_task_num: AtomicUsize::new(0),
        snowflaker,
    })
}

/// @Author: DengLibin
/// @Date: Create in 2024-07-18 11:01:34
/// @Description: 后台执行阻塞(耗时)任务,在阻塞线程池中执行,多余任务排队,不会占用工作线程
pub async fn execute_blocking_task<F>(task: F, task_name: String, app_state: Arc<AppState>)
where
    F: FnOnce() + Send + 'static,
{
    app_state.async_task_num.fetch_add(1, Ordering::SeqCst);
    task::spawn_blocking(move || {
        info!(
            "执行异步阻塞任务:{},任务数量:{}",
            task_name,
            app_state.async_task_num.load(Ordering::SeqCst)
        );
        task();
        app_state.async_task_num.fetch_sub(1, Ordering::SeqCst);
        info!(
            "执行异步阻塞任务:{}完成,剩余任务数量:{}",
            task_name,
            app_state.async_task_num.load(Ordering::SeqCst)
        );
    });
}
/// @Author: DengLibin
/// @Date: Create in 2024-07-18 11:02:00
/// @Description: 后台执行非阻塞任务,工作线程中执行,不要执行阻塞(耗时)任务,如果提交了大量阻塞或耗时任务会导致工作线程被占满,无法执行其他任务,导致其他任务等待
pub async fn execute_task<F>(task: F, task_name: String, app_state: Arc<AppState>)
where
    F: FnOnce() + Send + 'static,
{
    app_state.async_task_num.fetch_add(1, Ordering::SeqCst);
    task::spawn(async move {
        info!(
            "执行异步任务:{},任务数量:{}",
            task_name,
            app_state.async_task_num.load(Ordering::SeqCst)
        );
        task();
        app_state.async_task_num.fetch_sub(1, Ordering::SeqCst);
        info!(
            "执行异步任务:{}完成,剩余任务数量:{}",
            task_name,
            app_state.async_task_num.load(Ordering::SeqCst)
        );
    });
}
